<template>
  <view class="custom-swiper">
    <view class="swiper-content" :style="{
      height: `${swiperList.length * 100}vh`,
      transform: `translateY(calc(${basePosition}vh + ${translateY}px))`,
      transition: translateY === 0 ? 'transform 0.3s' : 'none',
    }" @touchstart="handleTouchStart" @touchmove="handleTouchMove" @touchend="handleTouchEnd"
    >
      <view v-for="item in visibleItems" :key="item.virtualIndex" class="swiper-item"
            :style="{ transform: `translateY(${item.virtualIndex * 100}%)` }"
      >
        <slot :attrs="{
          item: item.data,
          index: item.virtualIndex,
          isActive: item.virtualIndex === curIdx,
        }"
        ></slot>
      </view>
    </view>
  </view>
</template>

<script setup>
import { computed, ref } from 'vue'

const props = defineProps({
  swiperList: Array,
})
const pauseTime = 500
const curIdx = ref(0)
const translateY = ref(0)

let touchStartY = 0
let touchMoveY = 0
let isAnimating = false // 节流标志

// 只渲染当前项及其前后各一项
const visibleItems = computed(() => {
  const start = Math.max(0, curIdx.value - 1)
  const end = Math.min(props.swiperList.value.length, curIdx.value + 2)
  return props.swiperList.value.slice(start, end).map((item, index) => ({
    data: { ...item },
    virtualIndex: start + index,
  }))
})

// 计算当前项的位置
const basePosition = computed(() => -curIdx.value * 100)

function handleTouchStart(e) {
  if (isAnimating) return
  touchStartY = e.touches[0].clientY
  touchMoveY = 0
}

function handleTouchMove(e) {
  if (isAnimating) return
  e.preventDefault?.() // 阻止默认滚动
  e.stopPropagation?.()
  touchMoveY = e.touches[0].clientY
  const distance = touchMoveY - touchStartY
  if ((curIdx.value === 0 && distance > 0) || (curIdx.value === props.swiperList.value.length - 1 && distance < 0)) {
    translateY.value = distance * 0.3
    return
  }
  translateY.value = distance
}

let timer = null
function handleTouchEnd() {
  if (isAnimating) return

  const distance = touchMoveY - touchStartY
  if (Math.abs(distance) > 150 && touchMoveY !== 0) {
    isAnimating = true // 开始切换时设置动画状态
    if (distance > 0 && curIdx.value > 0) {
      curIdx.value -= 1
    }
    else if (distance < 0 && curIdx.value < props.swiperList.value.length - 1) {
      curIdx.value += 1
    }
    // 等待动画完成后重置状态
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      isAnimating = false
    }, pauseTime) // 与过渡动画时间保持一致
  }
  translateY.value = 0
}
</script>

<style lang="scss">
  .custom-swiper {
    width: 100vw;
    height: 100vh;
    overflow: hidden;
    position: fixed;
    top: 0;
    left: 0;

    .swiper-content {
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
    }

    .swiper-item {
      width: 100%;
      height: 100vh;
      position: absolute;
      top: 0;
      left: 0;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: transform 0.1s;
      will-change: transform;
    }
  }
</style>
